package com.ys.service.storage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.entity.business.TpProductActiveComponent;
import com.ys.entity.purchase.*;
import com.ys.entity.storage.*;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.enume.purchase.TcgOfflinePurchaseInStorageEnum;
import com.ys.enume.storage.TccAssembleEnum;
import com.ys.enume.storage.TccOfflineAssembleEnum;
import com.ys.enume.storage.TccStockFrozenRunningEnum;
import com.ys.enume.storage.TccStockSourceEnum;
import com.ys.mapper.purchase.TcgOfflinePurchaseInStorageMapper;
import com.ys.mapper.purchase.TcgPurchaseByPlanSonMapper;
import com.ys.mapper.purchase.TcgPurchasePlanGoodsMapper;
import com.ys.mapper.storage.*;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.storage.*;
import com.ys.service.sys.CommonApiService;
import com.ys.service.sys.PdfService;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.R;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.*;

@Service("tccOfflineAssembleService")
public class TccOfflineAssembleImpl implements TccOfflineAssembleService {
	private static final Logger logger = LoggerFactory.getLogger(TccOfflineAssembleImpl.class);

	@Autowired
	private StorageMapper storageMapper;
	@Autowired
	private TccOfflineAssembleMapper tccOfflineAssembleMapper;
	@Autowired
	private TccOfflineAssembleItemMapper tccOfflineAssembleItemMapper;
	@Autowired
	private TccOnlinePutonService tccOnlinePutonService;
	@Autowired
	private TccOnlineAssembleErrorService tccOnlineAssembleErrorService;
	@Autowired
	private TccStockControlService tccStockControlService;

	private final Long MENUID = MenuId.TCC_OfflineAssembleQd;

	@Autowired
	private CommonApiService<TccOfflineAssemble> commonApiServiceAssemble;

	@Autowired
	private PdfService pdfService;

	@Autowired
	private TcgPurchaseByPlanSonMapper tcgPurchasePlanSonMapper;

	@Autowired
	private TcgPurchasePlanGoodsMapper tcgPurchasePlanGoodsMapper;

	@Autowired
	private TcgOfflinePurchaseInStorageMapper tcgOfflinePurchaseInStorageMapper;


	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R pass(String bids) throws Exception {
		HashSet<String> listBid = new HashSet<String>();
		for(String bid : bids.split(",")) {
			listBid.add(bid);
		}
		for (String bid :listBid){
			TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
			if (tccOfflineAssemble == null) {
				return R.error("数据不存在!");
			} else if (tccOfflineAssemble.getState() != TccOfflineAssembleEnum.State.NOT.value) {
				return R.error("数据已组装!");
			//20250206 取消组装清单未打印的判断
//			}else if (tccOfflineAssemble.getAssemblyListBid() == null ) {
//				return R.error("数据组装清单未打印!");
			}else if (tccOfflineAssemble.getPrintStatus() ==  TccOfflineAssembleEnum.PrintStatus.NOT_PRINT.value) {
				return R.error("数据打印状态未打印!");
			}
			Integer count = new TcgOfflinePurchaseInStorage()
					.addLeftJoin("TCC_OfflineAssembleItem B ON B.offlinePurchaseStorageId = A.id")
					.addLeftJoin("TCC_OfflineAssemble C ON C.bid = b.pbid")
					.where("C.bid = '" + bid + "'  AND A.GenerateStatus IS NOT NULL")
					.count();
			if (count > 0) {
				return R.error("该数据没有采购母件,不允许正常组装!");
			}
			count = new TcgOfflinePurchaseInStorage()
					.addLeftJoin("TCC_OfflineAssembleItem B ON B.offlinePurchaseStorageId = A.id")
					.addLeftJoin("TCC_OfflineAssemble C ON C.bid = b.pbid")
					.where("C.bid = '" + bid + "'  AND A.JgSl != 0")
					.count();
			if (count > 0) {
				return R.error("该数据有子件加购,不允许正常组装!");
			}
		}

		for (String bid :listBid){
			TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
			tccOfflineAssemble
					.setParentAssembleNumber(tccOfflineAssemble.getParentPreAssembleNumber())
					.setState(TccOfflineAssembleEnum.State.NORMAL.value)
					.setAuditTime(new Date())
					.setAuditingUserId(ShiroUtils.getUserId());


			// 子件出库
			List<TccOfflineAssembleItem> listTccOfflineAssembleItem = new TccOfflineAssembleItem().setPbid(bid).queryList();
			if (listTccOfflineAssembleItem.size() == 0){
				throw new RuntimeException("组装子件数据为空!");
			}
			for(TccOfflineAssembleItem item : listTccOfflineAssembleItem) {
				// 子件的剩余数量更新为0/填充组装数量
				item.setSubAssembleLeftNum(0)
					.setSubRealStorageNum(item.getSubPlanStorageNum());
				tccOfflineAssembleItemMapper.update(item);

				Long stockControlId = item.getStockControlId();
				//冻结库存
				Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_FINISH.value;
				tccStockControlService.thaw(stockControlId, item.getSubPlanStorageNum(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());

				if (item.getSubPlanStorageNum() != 0){
					String remark = "线上商品组装单单号：" + bid + "，正常组装，子件出库";
					Integer numOut = item.getSubPlanStorageNum();
					Integer source = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
					tccStockControlService.outWithRunning(stockControlId, remark, numOut, bid,source,tccOfflineAssemble.getId());
				}
			}

			TcgOfflinePurchaseInStorage tcgOfflinePurchaseInStorage = new TcgOfflinePurchaseInStorage().setId(listTccOfflineAssembleItem.get(0).getOfflinePurchaseStorageId()).queryFirst();

			if (tccOfflineAssemble.getParentAssembleNumber() != 0) {
				// 母件入库
				R add;
				{
					String rkBid = bid;
					String chw = "HW00001";
					String productName = tcgOfflinePurchaseInStorage.getProductName();
					Integer productNum = tccOfflineAssemble.getParentAssembleNumber();
					String productCode = tcgOfflinePurchaseInStorage.getProductCode();
					Integer productNumAll = tccOfflineAssemble.getParentAssembleNumber();
					BigDecimal purchasePrice = storageMapper.countPurchaseByPurchasePlanSon(tcgOfflinePurchaseInStorage.getPurchaseOrderGoodsId());
					BigDecimal purchaseTotalPriceAll = purchasePrice.multiply(new BigDecimal(productNum));
					BigDecimal allotPrice = purchasePrice;
					BigDecimal totalAllotPrice = purchaseTotalPriceAll;
					String vgsbm = tcgOfflinePurchaseInStorage.getVgsbm();
					Date drksj = new Date();
					Integer isParent = 1;
					String sourceBid = bid;
					Integer source = TccStockSourceEnum.Source.TCC_Assemble.value;
					String remark = "";
					String companyVid = "C109";//默认问前
					add = tccStockControlService.inWithRunning(rkBid, chw, productName, productNum, productCode, productNumAll, purchasePrice, purchaseTotalPriceAll, allotPrice, totalAllotPrice, vgsbm, drksj, isParent, sourceBid, source, remark, companyVid, bid,tccOfflineAssemble.getId());
					if (add.getCode() != 0) {
						throw new RuntimeException(add.getMsg());
					}

					Long stockControlId = Long.valueOf(add.get("data").toString());
					//冻结库存
					Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_PASS.value;
					tccStockControlService.frozen(stockControlId, tccOfflineAssemble.getParentAssembleNumber(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());
					//保存库存id
					tccOfflineAssemble.setStockControlIdByIn(stockControlId);
				}
				// 生成质检上架单
				tccOnlinePutonService.add(bid, tcgOfflinePurchaseInStorage.getProductCode(), tccOfflineAssemble.getParentAssembleNumber(), Long.valueOf(add.get("data").toString()));

//				BigDecimal fJe =  new BigDecimal(tccOfflineAssemble.getParentAssembleNumber()).multiply(BigDecimal.ONE);
//				//划出流水,划出至仓储部,备注组装单，商品编码+商品名称+数量
//				tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyNoTrigger(
//						tcgOfflinePurchaseInStorage.getVgsbm(), "GS0608",  TransactionTypeEnum.BusinessType.TCC_Distribute_ZZ.name, fJe.negate(),
//						tccOfflineAssemble.getCreateTime(), tccOfflineAssemble.getAuditTime(),
//						"线上商品组装单:" + bid + "，商品编码:" + tcgOfflinePurchaseInStorage.getProductCode()+ "，商品名称:" + tcgOfflinePurchaseInStorage.getProductName()
//								+ "，数量:" + tccOfflineAssemble.getParentAssembleNumber(),
//						null, null, bid, null, null, null);
//				//划入流水
//				tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyNoTrigger(
//						"GS0608", tcgOfflinePurchaseInStorage.getVgsbm(),  TransactionTypeEnum.BusinessType.TCC_Distribute_ZZ.name, fJe,
//						tccOfflineAssemble.getCreateTime(), tccOfflineAssemble.getAuditTime(),
//						"线上商品组装单:" + bid + "，商品编码:" + tcgOfflinePurchaseInStorage.getProductCode()+ "，商品名称:" + tcgOfflinePurchaseInStorage.getProductName()
//								+ "，数量:" + tccOfflineAssemble.getParentAssembleNumber(),
//						null, null, bid, null, null, null);
			}
			//修改组装单信息
			tccOfflineAssembleMapper.update(tccOfflineAssemble);
		}
		return R.ok("组装成功");
	}
	
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R doError(String bid, Integer parentAssembleNumber, String detailArr) throws Exception {
		TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
		// 验证组装单
		if (tccOfflineAssemble == null) {
			return R.error("数据不存在");
		} else if (tccOfflineAssemble.getState() != TccOfflineAssembleEnum.State.NOT.value) {
			return R.error("数据已组装");
		//20250206 取消组装清单未打印的判断
//		}else if (tccOfflineAssemble.getAssemblyListBid() == null ) {
//			return R.error("数据组装清单未打印!");
		} else if (tccOfflineAssemble.getParentPreAssembleNumber() < parentAssembleNumber) {
			return R.error("组装数量超过预计组装数量");
		}else if (tccOfflineAssemble.getPrintStatus() ==  TccOfflineAssembleEnum.PrintStatus.NOT_PRINT.value) {
			return R.error("数据打印状态未打印!");
		}

		// 验证详情数据不能为空
		JSONArray detailJA = JSON.parseArray(detailArr);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}

		/*
		 *  验证详情数据剩余数量不能小于0
		 *  组装单子表数据与详情数据的ID一致
		 *  实际入库数量不能高于计划入库数量，实际入库数量= 母件组装数量*子件BOM数量+子件组装剩余数量
		 */
		List<TccOfflineAssembleItem> listTccOfflineAssembleItem = new TccOfflineAssembleItem().setPbid(bid).queryList();
		if (listTccOfflineAssembleItem.size() != detailJA.size()) {
			return R.error("子列表数据大小有误");
		}
		Map<Long, TccOfflineAssembleItem> ID_ENTITY_MAP = new HashMap<Long, TccOfflineAssembleItem>();
		for(TccOfflineAssembleItem item : listTccOfflineAssembleItem) {
			ID_ENTITY_MAP.put(item.getId(), item);
		}
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			Integer subLeftNumber = detailJO.getInteger("subLeftNumber");
			if (subLeftNumber == null || subLeftNumber < 0) {
				return R.error("子件剩余数量不能为负");
			}

			Long id = detailJO.getLong("id");
			if (!ID_ENTITY_MAP.containsKey(id)) {
				return R.error("数据有误");
			}

			// 实际入库数量不能高于子件计划入库数量
			Integer subRealStorageNum = parentAssembleNumber * detailJO.getInteger("subBomNumber") + subLeftNumber;
			TccOfflineAssembleItem item = ID_ENTITY_MAP.get(id);
			if (subRealStorageNum > item.getSubPlanStorageNum()) {
				return R.error("剩余数量与组装数量总和不能高于计划入库数量");
			}
		}

		tccOfflineAssemble
			.setParentAssembleNumber(parentAssembleNumber)
			.setState(TccOfflineAssembleEnum.State.ABNORMAL.value)
			.setAuditTime(new Date())
			.setAuditingUserId(ShiroUtils.getUserId());


		List<TccOnlineAssembleErrorItemByAdd> tccOnlineAssembleErrorItems = new ArrayList<>();

		TcgOfflinePurchaseInStorage tcgOfflinePurchaseInStorage = null;
		// 子件出库
		for(int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			Long id = detailJO.getLong("id");
			TccOfflineAssembleItem item = ID_ENTITY_MAP.get(id);
			Integer subLeftNumber = detailJO.getInteger("subLeftNumber");

			// 子件组装实际入库数量 = 母件组装数量 * 子件BOM数量
			Integer subRealStorageNum = parentAssembleNumber * detailJO.getInteger("subBomNumber");

			// 更新组装单子表的子件剩余数量和子件实际入库数量
			storageMapper.updateTccOfflineAssembleItemOfNum(id, subLeftNumber, subRealStorageNum);

			Long stockControlId = item.getStockControlId();

			//解冻库存
			Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_FINISH.value;
			tccStockControlService.thaw(stockControlId, item.getSubPlanStorageNum(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());

			String remark = "线上商品组装单单号：" + bid + "，异常组装，子件缺失出库";
			// 出库数量 = 子件所有数量
			Integer numOut = item.getSubPlanStorageNum();
			Integer sourceTypeOut = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
			tccStockControlService.outWithRunning(stockControlId, remark, numOut, bid,sourceTypeOut,tccOfflineAssemble.getId());


			// 子件缺失数量 = 子件计划入库数量-子件实际入库数量 - 剩余数量
			Integer subAssembleLostNum = item.getSubPlanStorageNum() - subRealStorageNum - subLeftNumber;

			// 生成组装报错单，缺失数量大于0才生成
			if (subAssembleLostNum > 0) {
				//查询入库数据
				tcgOfflinePurchaseInStorage = new TcgOfflinePurchaseInStorage().setId(item.getOfflinePurchaseStorageId()).queryFirst();
				Map<String, Object> tcgPurchaseOrderSon = new TcgPurchaseByOrderSon().setId(tcgOfflinePurchaseInStorage.getPurchaseOrderSonId())
						.addLeftJoin("TCG_PurchaseByOrder B ON A.pid = B.id")
						.addField("B.bid")
						.queryFirstMap();
				String purchaseOrderBid  = tcgPurchaseOrderSon.get("bid").toString();

				TccOnlineAssembleErrorItemByAdd tccOnlineAssembleErrorItem = new TccOnlineAssembleErrorItemByAdd();
				tccOnlineAssembleErrorItem.setSubAssembleLostNum(subAssembleLostNum);
				tccOnlineAssembleErrorItem.setAssembleItemId(id);
				tccOnlineAssembleErrorItem.setSubAmount(tcgOfflinePurchaseInStorage.getSubPurchasePrice());
				tccOnlineAssembleErrorItem.setSubCode(tcgOfflinePurchaseInStorage.getSubCode());
				tccOnlineAssembleErrorItem.setOrderBid(purchaseOrderBid);
				tccOnlineAssembleErrorItems.add(tccOnlineAssembleErrorItem);
			}
		}
		//有缺失才允许报错
		if (tccOnlineAssembleErrorItems.size() != 0){
			tccOnlineAssembleErrorService.add(tccOfflineAssemble.getId(), tccOnlineAssembleErrorItems);
		}


		// 剩余子件入库
		for(int i = 0; i < detailJA.size(); i++) {

			JSONObject detailJO = detailJA.getJSONObject(i);
			Long id = detailJO.getLong("id");
			TccOfflineAssembleItem item = ID_ENTITY_MAP.get(id);
			Integer subLeftNumber = detailJO.getInteger("subLeftNumber");

			if (subLeftNumber > 0) {
				tcgOfflinePurchaseInStorage = new TcgOfflinePurchaseInStorage().setId(item.getOfflinePurchaseStorageId()).queryFirst();

				Long stockControlId = item.getStockControlId();
				TccStockControl tccStockControl = new TccStockControl().setId(stockControlId).queryFirst();
				String rkBid = bid;
				String chw = tccStockControl.getChw();
				String productName = tcgOfflinePurchaseInStorage.getSubName();
				Integer productNum = subLeftNumber;
				String productCode = tcgOfflinePurchaseInStorage.getSubCode();
				Integer productNumAll = subLeftNumber;
				BigDecimal purchasePrice = tcgOfflinePurchaseInStorage.getSubPurchasePrice();
				BigDecimal purchaseTotalPriceAll = purchasePrice.multiply(new BigDecimal(productNum));
				BigDecimal allotPrice = null;
				BigDecimal totalAllotPrice = null;
				String vgsbm = tcgOfflinePurchaseInStorage.getVgsbm();
				Date drksj = new Date();
				Integer isParent = 0;
				String sourceBid = bid;
				Integer sourceType = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
				String remark = "商品组装单单号：" + bid + "，异常组装，剩余子件入库";
				String companyVid = "C109";
				String assembleBid = bid;
				R add = tccStockControlService.inWithRunning(rkBid, chw, productName, productNum, productCode, productNumAll, purchasePrice, purchaseTotalPriceAll, allotPrice, totalAllotPrice, vgsbm, drksj, isParent, sourceBid, sourceType, remark, companyVid, assembleBid,tccOfflineAssemble.getId());
				if (add.getCode() != 0) {
					throw new RuntimeException(add.getMsg());
				}
				Long stockControlIdByNew = Long.valueOf(add.get("data").toString());
				TccOfflineAssembleItem tccOfflineAssembleItemByNew = new TccOfflineAssembleItem()
						.setStockControlIdByNew(stockControlIdByNew)
						.setId(item.getId());
				tccOfflineAssembleItemMapper.update(tccOfflineAssembleItemByNew);
			}
		}
		if (tccOfflineAssemble.getParentAssembleNumber() != 0) {
			// 母件入库
			R add;
			{
				String rkBid = bid;
				String chw = "HW00001";
				String productName = tcgOfflinePurchaseInStorage.getProductName();
				Integer productNum = tccOfflineAssemble.getParentAssembleNumber();
				String productCode = tcgOfflinePurchaseInStorage.getProductCode();
				Integer productNumAll = tccOfflineAssemble.getParentAssembleNumber();
				BigDecimal purchasePrice = storageMapper.countPurchaseByPurchasePlanSon(tcgOfflinePurchaseInStorage.getPurchaseOrderGoodsId());
				BigDecimal purchaseTotalPriceAll = purchasePrice.multiply(new BigDecimal(productNum));
				BigDecimal allotPrice = purchasePrice;
				BigDecimal totalAllotPrice = purchaseTotalPriceAll;
				String vgsbm = tcgOfflinePurchaseInStorage.getVgsbm();
				Date drksj = new Date();
				Integer isParent = 1;
				String sourceBid = bid;
				Integer sourceType = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
				String remark = "";
				String companyVid = "C109";
				add = tccStockControlService.inWithRunning(rkBid, chw, productName, productNum, productCode, productNumAll, purchasePrice, purchaseTotalPriceAll, allotPrice, totalAllotPrice, vgsbm, drksj, isParent, sourceBid, sourceType, remark, companyVid, bid,tccOfflineAssemble.getId());

				if (add.getCode() != 0) {
					throw new RuntimeException(add.getMsg());
				}

				Long stockControlId = Long.valueOf(add.get("data").toString());
				//冻结库存
				Integer sourceTypeFrozen = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_PASS.value;
				tccStockControlService.frozen(stockControlId, tccOfflineAssemble.getParentAssembleNumber(), sourceTypeFrozen, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());
				//保存库存id
				tccOfflineAssemble.setStockControlIdByIn(stockControlId);

			}

			// 生成质检上架单
			tccOnlinePutonService.add(bid, tcgOfflinePurchaseInStorage.getProductCode(), tccOfflineAssemble.getParentAssembleNumber(), Long.valueOf(add.get("data").toString()));


//			BigDecimal fJe = new BigDecimal(tccOfflineAssemble.getParentAssembleNumber()).multiply(BigDecimal.ONE);
//			//划出流水,划出至仓储部,备注组装单，商品编码+商品名称+数量
//			tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyNoTrigger(
//					tcgOfflinePurchaseInStorage.getVgsbm(), "GS0608", TransactionTypeEnum.BusinessType.TCC_Distribute_ZZ.name, fJe.negate(),
//					tccOfflineAssemble.getCreateTime(), tccOfflineAssemble.getAuditTime(),
//					"线上商品组装单:" + bid + "，商品编码:" + tcgOfflinePurchaseInStorage.getProductCode() + "，商品名称:" + tcgOfflinePurchaseInStorage.getProductName()
//							+ "，数量:" + tccOfflineAssemble.getParentAssembleNumber(),
//					null, null, bid, null, null, null);
//			//划入流水
//			tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyNoTrigger(
//					"GS0608", tcgOfflinePurchaseInStorage.getVgsbm(), TransactionTypeEnum.BusinessType.TCC_Distribute_ZZ.name, fJe,
//					tccOfflineAssemble.getCreateTime(), tccOfflineAssemble.getAuditTime(),
//					"线上商品组装单:" + bid + "，商品编码:" + tcgOfflinePurchaseInStorage.getProductCode() + "，商品名称:" + tcgOfflinePurchaseInStorage.getProductName()
//							+ "，数量:" + tccOfflineAssemble.getParentAssembleNumber(),
//					null, null, bid, null, null, null);
		}
		//修改组装单信息
		tccOfflineAssembleMapper.update(tccOfflineAssemble);
		return R.ok("异常报错成功!");
	}


	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R printing(String bids) throws Exception {
		try {


			HashSet<String> listBid = new HashSet<String>();
			for (String bid : bids.split(",")) {
				listBid.add(bid);
			}
			//生成组装清单
			String assemblyListBid = commonApiServiceAssemble.getCommonNextBid(MENUID);

			List<ZuzhuangDto.RowDto> rowDtoList = new ArrayList<>();
			for (String bid : listBid) {
				TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
				tccOfflineAssemble.setAssemblyListBid(assemblyListBid);
				tccOfflineAssembleMapper.update(tccOfflineAssemble);


				List<Map<String, Object>> tccOfflineAssembleItemList = new TccOfflineAssembleItem()
						.addLeftJoin("TCG_OfflinePurchaseInStorage opi on opi.id = A.offlinePurchaseStorageId")
						.addField("opi.subCode")//子件编码
						.addField("opi.subName")//子件名称
						.addField("opi.subBomNumber")//子件BOM数量
						.addField("opi.productCode")//商品编码
						.addField("opi.productName")//商品名称
						.addLeftJoin("TP_ProductActive pa ON pa.code = opi.productCode ")//商品信息
						.addField("pa.sizeLength")
						.addField("pa.sizeWidth")
						.addField("pa.sizeHeight")
						.addLeftJoin("THR_OperateCompanyApply EE ON EE.Vgsbm = opi.Vgsbm ")//运营公司管理表
						.addField("EE.Vgsjc AS vgsjc")//采购公司简称
						.addField("EE.vgsbm AS vgsbm")//采购公司编码
						.addLeftJoin("TCG_PurchaseByOrderSon C ON C.id = opi.PurchaseOrderSonId")
						.addLeftJoin("TCG_PurchaseByOrder AA ON C.Pid = AA.id")
						.addField("AA.aliLogisticsBillNo AS aliLogisticsBillNo,AA.Bid purchaseOrderBid")
						.addLeftJoin("TCG_PurchaseByPlanSon E ON  E.Id = C.PurchasePlanSonId ")//采购计划子件
						.addField("E.JgSl AS jgSl")//子件加购数量
						.addField("E.SubTotalAmount AS subTotalAmount")//子件采购总数
						.addLeftJoin("TCC_Location CC ON CC.Chw = opi.Chw")
						.addLeftJoin("TCC_WarehouseArea CWA ON CWA.Ckq = CC.Ckq")//库区
						.addLeftJoin("TCC_Warehouse CW ON CW.Cck = CWA.Cck")//仓库
						.addField("CW.vck,CWA.vkq,CC.vhw")
						.setPbid(tccOfflineAssemble.getBid())
						.queryMap();

				List<ZuzhuangDto.RowDto.BomDto> bomDtoList = new ArrayList<>();
				for (Map<String, Object> map : tccOfflineAssembleItemList) {
					ZuzhuangDto.RowDto.BomDto bomDto = new ZuzhuangDto.RowDto.BomDto(map.get("purchaseOrderBid").toString(), map.get("aliLogisticsBillNo").toString(),
							map.get("subCode").toString(), map.get("subName").toString(), map.get("subBomNumber").toString(), map.get("subRealStorageNum").toString()
							, map.get("jgSl").toString(), map.get("subTotalAmount").toString(), map.get("subAssembleLeftNum").toString(), map.get("vhw").toString());
					bomDtoList.add(bomDto);
				}

				Map<String, Object> tccOfflineAssembleItemMap = tccOfflineAssembleItemList.get(0);
				ZuzhuangDto.RowDto rowDto = new ZuzhuangDto.RowDto(bid, tccOfflineAssembleItemMap.get("vgsbm").toString(), tccOfflineAssembleItemMap.get("vgsjc").toString()
						, tccOfflineAssembleItemMap.get("productCode").toString(), tccOfflineAssembleItemMap.get("productName").toString(),
						new BigDecimal(tccOfflineAssembleItemMap.get("sizeLength").toString()).stripTrailingZeros().toPlainString() + "*"+
						new BigDecimal(tccOfflineAssembleItemMap.get("sizeWidth").toString()).stripTrailingZeros().toPlainString() + "*"+
						new BigDecimal(tccOfflineAssembleItemMap.get("sizeHeight").toString()).stripTrailingZeros().toPlainString()
						, tccOfflineAssemble.getParentPreAssembleNumber().toString(), tccOfflineAssemble.getParentAssembleNumber().toString(), bomDtoList);
				rowDtoList.add(rowDto);
			}
			ZuzhuangDto zuzhuangDto = new ZuzhuangDto(assemblyListBid, rowDtoList);
			String url = pdfService.generateGoodsPDF_ZZQD(zuzhuangDto);
			return R.ok(url);
		}catch (Exception e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
	}

	@Data
	@AllArgsConstructor
	public static class ZuzhuangDto{
		private String assemblyListBid; // 组装清单
		private List<RowDto> rows; // 明细

		@Data
		@AllArgsConstructor
		public static class RowDto {
			private String bid; // 组装单号
			private String vgsbm; // 公司编码
			private String vgsjc; // 公司简称
			private String productCode; // 商品编码
			private String productName; // 商品名称
			private String size; // 商品尺寸（长*宽*高）
			private String subPlanStorageNum; // 组装数量
			private String parentAssembleNumber; // 实际组装数量
			private List<BomDto> boms; // BOM子件数组

			@Data
			@AllArgsConstructor
			public static class BomDto {
				private String purchaseOrderBid; // 采购订单
				private String aliLogisticsBillNo; // 物流运单号
				private String subCode; // 子件编码
				private String subName; // 子件名称
				private String subBomNumber; // 子件BOM数量
				private String subRealStorageNum; //子件组装数量
				private String jgSl; //子件加购数量
				private String subTotalAmount; //子件采购总数
				private String subAssembleLeftNum; //剩余数量
				private String vhw; //货位
			}
		}
	}

	/**
	 * 入库箱标打印
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R getPdf(Map<String, Object> params) throws Exception{
		String url = null;
		try {
			if (params.get("listId") == null) {
				return R.error("线上商品组装数据未选择!");
			}
			if (params.get("listOfflineAssembleId") == null) {
				return R.error("线上商品组装数据未选择!");
			}

			String listId = params.get("listId").toString();
			String[] split = (listId.substring(1, listId.length() - 1)).split(",");

			HashSet<String> listPurchaseOrderId = new HashSet<String>();
			for (String purchaseOrderId : split) {
				listPurchaseOrderId.add(purchaseOrderId);
			}

			List<StockInDto> stockInDtoList = new ArrayList<>();
			for (String purchaseOrderId : listPurchaseOrderId) {
				//订单信息
				Map<String,Object> tcgPurchaseByOrder = new TcgPurchaseByOrder()
						.addLeftJoin("THR_OperateCompanyApply E ON E.Vgsbm = A.Vgsbm ")//运营公司管理表
						.addField("E.Vgsjc AS vgsjc")//采购公司简称
						.addLeftJoin("TCG_PurchasePlanGoods I ON I.Id = A.PurchasePlanGoodsId")//采购计划母件表
						.addField("I.SpAmount AS spAmount")//采购数量
						.addLeftJoin("TP_ProductActive G ON G.Code = A.SpBm ")//商品母件信息表
						.addField("G.Name AS spName")//商品名称
						.addField("G.img")//商品图片
						.addField("CASE WHEN A.PlanToOrderNo IS NOT NULL  THEN CAST(A.PlanToOrderNo AS varchar(50)) + '/' +  CAST(A.PlanToOrderNum AS varchar(50)) + ' ' + A.CreateMonth + '-NO.' + CAST(A.MonthNo AS varchar(50)) ELSE '' END  assembleSign ")//组装标识
						.where("A.id = " + purchaseOrderId)
						.queryFirstMap();

				//采购清单信息
				List<Map<String, Object>> tcgPurchaseByOrderSonList = new TcgPurchaseByOrderSon()
						.addLeftJoin("TCG_PurchaseByPlanSon E ON  E.Id = A.PurchasePlanSonId ")//采购计划子件
						.addField("E.subCode AS subCode")//子件商品编码
						.addField("E.SubName AS subName")//子件商品名称
						.addField("E.PurchaseAmount AS purchaseAmount")//子件采购数量
						.addField("E.JgSl AS jgSl")//子件加购数量
						.addField("E.SubTotalAmount AS subTotalAmount")//子件采购总数
						.where("A.pid = " + tcgPurchaseByOrder.get("id"))
						.setOrderby("A.subCode ASC")
						.queryMap();

				//组装Bom
				List<TpProductActiveComponent> tpProductActiveComponentList = new TpProductActiveComponent()
						.setPcode(tcgPurchaseByOrder.get("spBm").toString())
						.setOrderby("A.code ASC")
						.queryList();

				List<StockInDto.RowDto> rows = new ArrayList<StockInDto.RowDto>();
				for (Map<String, Object>  tcgPurchaseByOrderSon :tcgPurchaseByOrderSonList){
					rows.add(new StockInDto.RowDto(tcgPurchaseByOrderSon.get("subCode").toString(),tcgPurchaseByOrderSon.get("subName").toString(), new BigDecimal(tcgPurchaseByOrderSon.get("purchaseAmount").toString()).stripTrailingZeros().toPlainString()
							,new BigDecimal(tcgPurchaseByOrderSon.get("jgSl").toString()).stripTrailingZeros().toPlainString()
							,new BigDecimal(tcgPurchaseByOrderSon.get("subTotalAmount").toString()).stripTrailingZeros().toPlainString()
					));
				}

				List<StockInDto.BomDto> boms = new ArrayList<StockInDto.BomDto>();
				for (TpProductActiveComponent tpProductActiveComponent : tpProductActiveComponentList){
					boms.add(new StockInDto.BomDto(tpProductActiveComponent.getCode(),tpProductActiveComponent.getName(),tpProductActiveComponent.getNum().stripTrailingZeros().toPlainString()));
				}

				StockInDto stockInDto = new StockInDto(tcgPurchaseByOrder.get("bid").toString(),tcgPurchaseByOrder.get("vgsbm").toString(),tcgPurchaseByOrder.get("vgsjc").toString()
						,tcgPurchaseByOrder.get("spBm").toString() + "/" + tcgPurchaseByOrder.get("spName").toString(),tcgPurchaseByOrder.get("spAmount").toString(),
						tcgPurchaseByOrder.get("img").toString(),tcgPurchaseByOrder.get("assembleSign").toString(),tcgPurchaseByOrder.get("aliLogisticsBillNo").toString(),rows,boms);

				stockInDtoList.add(stockInDto);
			}
			url = pdfService.generateGoodsPDF_RKXB(stockInDtoList);

			String listOfflineAssembleId = params.get("listOfflineAssembleId").toString();
			String[] splitOfflineAssembleId = (listOfflineAssembleId.substring(1, listOfflineAssembleId.length() - 1)).split(",");

			HashSet<String> offlineAssembleIdList = new HashSet<String>();
			for (String offlineAssembleId : splitOfflineAssembleId) {
				offlineAssembleIdList.add(offlineAssembleId);
			}

			for (String id : offlineAssembleIdList) {
				TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setId(Long.valueOf(id)).queryFirst();
				tccOfflineAssemble.setPrintStatus(TccOfflineAssembleEnum.PrintStatus.IS_PRINT.value);
				tccOfflineAssembleMapper.update(tccOfflineAssemble);
			}
			return R.ok(url);
		}catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * 质检上架入库箱标打印
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R getPdfZj(Map<String, Object> params) throws Exception{
		String url = null;
		try {
			if (params.get("listId") == null) {
				return R.error("线上商品组装数据未选择!");
			}

			String listId = params.get("listId").toString();
			String[] split = (listId.substring(1, listId.length() - 1)).split(",");

			HashSet<String> listPurchaseOrderId = new HashSet<String>();
			for (String purchaseOrderId : split) {
				listPurchaseOrderId.add(purchaseOrderId);
			}

			List<StockInDto> stockInDtoList = new ArrayList<>();
			for (String purchaseOrderId : listPurchaseOrderId) {
				//订单信息
				Map<String,Object> tcgPurchaseByOrder = new TcgPurchaseByOrder()
						.addLeftJoin("THR_OperateCompanyApply E ON E.Vgsbm = A.Vgsbm ")//运营公司管理表
						.addField("E.Vgsjc AS vgsjc")//采购公司简称
						.addLeftJoin("TCG_PurchasePlanGoods I ON I.Id = A.PurchasePlanGoodsId")//采购计划母件表
						.addField("I.SpAmount AS spAmount")//采购数量
						.addLeftJoin("TP_ProductActive G ON G.Code = A.SpBm ")//商品母件信息表
						.addField("G.Name AS spName")//商品名称
						.addField("G.img")//商品图片
						.addField("CASE WHEN A.PlanToOrderNo IS NOT NULL  THEN CAST(A.PlanToOrderNo AS varchar(50)) + '/' +  CAST(A.PlanToOrderNum AS varchar(50)) + ' ' + A.CreateMonth + '-NO.' + CAST(A.MonthNo AS varchar(50)) ELSE '' END  assembleSign ")//组装标识
						.where("A.id = " + purchaseOrderId)
						.queryFirstMap();

				//采购清单信息
				List<Map<String, Object>> tcgPurchaseByOrderSonList = new TcgPurchaseByOrderSon()
						.addLeftJoin("TCG_PurchaseByPlanSon E ON  E.Id = A.PurchasePlanSonId ")//采购计划子件
						.addField("E.subCode AS subCode")//子件商品编码
						.addField("E.SubName AS subName")//子件商品名称
						.addField("E.PurchaseAmount AS purchaseAmount")//子件采购数量
						.addField("E.JgSl AS jgSl")//子件加购数量
						.addField("E.SubTotalAmount AS subTotalAmount")//子件采购总数
						.where("A.pid = " + tcgPurchaseByOrder.get("id"))
						.setOrderby("A.subCode ASC")
						.queryMap();

				//组装Bom
				List<TpProductActiveComponent> tpProductActiveComponentList = new TpProductActiveComponent()
						.setPcode(tcgPurchaseByOrder.get("spBm").toString())
						.setOrderby("A.code ASC")
						.queryList();

				List<StockInDto.RowDto> rows = new ArrayList<StockInDto.RowDto>();
				for (Map<String, Object>  tcgPurchaseByOrderSon :tcgPurchaseByOrderSonList){
					rows.add(new StockInDto.RowDto(tcgPurchaseByOrderSon.get("subCode").toString(),tcgPurchaseByOrderSon.get("subName").toString(), new BigDecimal(tcgPurchaseByOrderSon.get("purchaseAmount").toString()).stripTrailingZeros().toPlainString()
							,new BigDecimal(tcgPurchaseByOrderSon.get("jgSl").toString()).stripTrailingZeros().toPlainString()
							,new BigDecimal(tcgPurchaseByOrderSon.get("subTotalAmount").toString()).stripTrailingZeros().toPlainString()
					));
				}

				List<StockInDto.BomDto> boms = new ArrayList<StockInDto.BomDto>();
				for (TpProductActiveComponent tpProductActiveComponent : tpProductActiveComponentList){
					boms.add(new StockInDto.BomDto(tpProductActiveComponent.getCode(),tpProductActiveComponent.getName(),tpProductActiveComponent.getNum().stripTrailingZeros().toPlainString()));
				}

				StockInDto stockInDto = new StockInDto(tcgPurchaseByOrder.get("bid").toString(),tcgPurchaseByOrder.get("vgsbm").toString(),tcgPurchaseByOrder.get("vgsjc").toString()
						,tcgPurchaseByOrder.get("spBm").toString() + "/" + tcgPurchaseByOrder.get("spName").toString(),tcgPurchaseByOrder.get("spAmount").toString(),
						tcgPurchaseByOrder.get("img").toString(),tcgPurchaseByOrder.get("assembleSign").toString(),tcgPurchaseByOrder.get("aliLogisticsBillNo").toString(),rows,boms);

				stockInDtoList.add(stockInDto);
			}
			url = pdfService.generateGoodsPDF_RKXB(stockInDtoList);

			return R.ok(url);
		}catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	@Data
	@AllArgsConstructor
	public static class StockInDto{
		private String codeCgdd; // 采购订单号
		private String codeCompany; // 公司编码
		private String nameCompany; // 公司简称
		private String infoGoods; // 商品信息
		private String spAmount; // 组装数量
		private String img; // 商品图片
		private String assembleSign; // 组装材料
		private String aliLogisticsBillNo; // 物流运单号
		private List<RowDto> rows; // 采购清单数组
		private List<BomDto> boms; // BOM子件数组

		@Data
		@AllArgsConstructor
		public static class RowDto {
			private String subCode; // 商品编码
			private String subName; // 商品名称
			private String purchaseAmount; // 组装采购数量
			private String jgSl; // 子件加购数量
			private String subTotalAmount; // 子件采购总数
		}

		@Data
		@AllArgsConstructor
		public static class BomDto {
			private String codeGoods; // 商品编码
			private String nameGoods; // 商品名称
			private String num; // 采购数量
		}
	}



	//从质检上架 回退
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R doBack(String bids) throws Exception {
		HashSet<String> listBid = new HashSet<String>();
		for(String bid : bids.split(",")) {
			listBid.add(bid);
		}
		for (String bid :listBid){
			TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
			if (tccOfflineAssemble == null) {
				return R.error("数据不存在!");
			}
		}
		for (String bid :listBid){
			TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
			logger.info("从质检上架 回退 原组装单数据："+tccOfflineAssemble);
			//int stateByOld = tccOfflineAssemble.getState();//旧状态
			tccOfflineAssemble
					//.setParentAssembleNumber(tccOfflineAssemble.getParentPreAssembleNumber())
					.setState(TccOfflineAssembleEnum.State.NOT.value)//未组装
					//.setAuditTime(new Date())
					//.setAuditingUserId(ShiroUtils.getUserId())
			;
			tccOfflineAssembleMapper.update(tccOfflineAssemble);

			// 子件入库
			List<TccOfflineAssembleItem> listTccOfflineAssembleItem = new TccOfflineAssembleItem().setPbid(bid).queryList();
			if (listTccOfflineAssembleItem.size() == 0){
				throw new RuntimeException("组装子件数据为空!");
			}
			logger.info("从质检上架 回退 原组装单子件数据："+listTccOfflineAssembleItem);
			for(TccOfflineAssembleItem item : listTccOfflineAssembleItem) {

				// 子件的剩余数量改回
				item.setSubAssembleLeftNum(item.getSubPlanStorageNum())
						.setSubRealStorageNum(0);
				tccOfflineAssembleItemMapper.update(item);

				Long stockControlId = item.getStockControlId();
				//入库
				if (item.getSubAssembleLeftNum() != 0){
					String remark = "线上商品组装单单号：" + bid + "，组装回退，子件入库";
					Integer numIn = item.getSubAssembleLeftNum();
					Integer source = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
					tccStockControlService.outWithRunning(stockControlId, remark, numIn * -1, bid,source,tccOfflineAssemble.getId());
				}
				//冻结库存
				Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_BACK_DJ.value;
				tccStockControlService.frozen(stockControlId, item.getSubPlanStorageNum(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());
			}

			//TcgOfflinePurchaseInStorage tcgOfflinePurchaseInStorage = new TcgOfflinePurchaseInStorage().setId(listTccOfflineAssembleItem.get(0).getOfflinePurchaseStorageId()).queryFirst();
			if (tccOfflineAssemble.getParentAssembleNumber() != 0) {
				//母件出库
				if(tccOfflineAssemble.getStockControlIdByIn()!=null){
					//解冻库存
					Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_BACK_JD.value;
					tccStockControlService.thaw(tccOfflineAssemble.getStockControlIdByIn(), tccOfflineAssemble.getParentAssembleNumber(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());
					//出库
					Integer sourceTypeByRunning = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
					tccStockControlService.outWithRunning(
							tccOfflineAssemble.getStockControlIdByIn(),
							"线上商品组装单单号：" + bid + "，组装回退，母件出库",
							tccOfflineAssemble.getParentAssembleNumber(),
							tccOfflineAssemble.getBid(),sourceTypeByRunning,tccOfflineAssemble.getId());
				}else {
					throw new RuntimeException("该组装单未记录库存id信息");
				}
				// 删除质检上架单
				tccOnlinePutonService.delByAssembleBid(bid);

			}
		}
		return R.ok("组装回退成功");
	}




	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R doErrorBack(String bid, List<TccOnlineAssembleErrorItem> tccOnlineAssembleErrorItems) throws Exception {
		TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();
		Integer parentAssembleNumber = tccOfflineAssemble.getParentAssembleNumber();
		// 验证组装单
		if (tccOfflineAssemble == null) {
			return R.error("数据不存在");
		}

		logger.info("从质检上架（异常组装） 回退 原组装单数据："+tccOfflineAssemble);
		/*
		 *  验证详情数据剩余数量不能小于0
		 *  组装单子表数据与详情数据的ID一致
		 *  实际入库数量不能高于计划入库数量，实际入库数量= 母件组装数量*子件BOM数量+子件组装剩余数量
		 */
		List<TccOfflineAssembleItem> listTccOfflineAssembleItem = new TccOfflineAssembleItem().setPbid(bid).queryList();

		logger.info("从质检上架（异常组装） 回退 原组装单子表数据："+listTccOfflineAssembleItem);
		Map<Long, TccOfflineAssembleItem> ID_ENTITY_MAP = new HashMap<Long, TccOfflineAssembleItem>();
		for(TccOfflineAssembleItem item : listTccOfflineAssembleItem) {
			ID_ENTITY_MAP.put(item.getId(), item);
		}

		tccOfflineAssemble
				//.setParentAssembleNumber(parentAssembleNumber)
				.setState(TccOfflineAssembleEnum.State.NOT.value)
				//.setAuditTime(new Date())
				//.setAuditingUserId(ShiroUtils.getUserId())
		;

		//List<TccOnlineAssembleErrorItem> tccOnlineAssembleErrorItems = new ArrayList<>();
		String purchaseOrderBid = null;
		TcgOfflinePurchaseInStorage tcgOfflinePurchaseInStorage = null;
		// 子件出库
		for(int i = 0; i < tccOnlineAssembleErrorItems.size(); i++) {
			//JSONObject detailJO = detailJA.getJSONObject(i);
			TccOnlineAssembleErrorItem detailJO = tccOnlineAssembleErrorItems.get(i);
			Long id = detailJO.getAssembleItemId();
			TccOfflineAssembleItem item = ID_ENTITY_MAP.get(id);
			Integer subLeftNumber = item.getSubAssembleLeftNum();

			// 子件组装实际入库数量 = 母件组装数量 * 子件BOM数量
			//Integer subRealStorageNum = parentAssembleNumber * detailJO.getInteger("subBomNumber");
			Integer subRealStorageNum = item.getSubRealStorageNum();

			// 更新组装单子表的子件剩余数量和子件实际入库数量
			storageMapper.updateTccOfflineAssembleItemOfNum(id, item.getSubPlanStorageNum(), 0);

			Long stockControlId = item.getStockControlId();


			String remark = "线上商品组装单单号：" + bid + "，组装回退，子件缺失出库";
			// 入库数量 = 实际组装消耗的数量
			//Integer numOut = subRealStorageNum;
			Integer numOut = item.getSubPlanStorageNum();
			Integer sourceTypeOut = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
			tccStockControlService.outWithRunning(stockControlId, remark, numOut * -1, bid,sourceTypeOut,tccOfflineAssemble.getId());

			//冻结库存
			Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_FINISH.value;
			tccStockControlService.frozen(stockControlId, item.getSubPlanStorageNum(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());


			// 子件缺失数量 = 子件计划入库数量-子件实际入库数量
			//Integer subAssembleLostNum = item.getSubPlanStorageNum() - subRealStorageNum;
			Integer subAssembleLostNum = detailJO.getSubAssembleLostNum();

			// 剩余子件出库
			if(subLeftNumber>0){
				if(item.getStockControlIdByNew()!=null){
					Integer sourceTypeByRunning = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
					tccStockControlService.outWithRunning(
							item.getStockControlIdByNew(),
							"线上商品组装单单号：" + bid + "，组装回退，子件出库",
							subLeftNumber,
							tccOfflineAssemble.getBid(),sourceTypeByRunning,item.getId());
				}else {
					throw new RuntimeException("该组装单未记录库存id信息");
				}
			}


		}
		//删除报错单
		tccOnlineAssembleErrorService.delByAssembleBid(tccOfflineAssemble.getId());

		if (tccOfflineAssemble.getParentAssembleNumber() != 0) {
			//母件出库
			if(tccOfflineAssemble.getStockControlIdByIn()!=null){
				Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_BACK_JD.value;
				//解冻库存
				tccStockControlService.thaw(tccOfflineAssemble.getStockControlIdByIn(), tccOfflineAssemble.getParentAssembleNumber(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());
				//出库
				Integer sourceTypeByRunning = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
				tccStockControlService.outWithRunning(
						tccOfflineAssemble.getStockControlIdByIn(),
						"线上商品组装单单号：" + bid + "，组装回退，母件出库",
						tccOfflineAssemble.getParentAssembleNumber(),
						tccOfflineAssemble.getBid(),sourceTypeByRunning,tccOfflineAssemble.getId());
			}else {
				throw new RuntimeException("该组装单未记录库存id信息");
			}
			//删除质检上架单
			tccOnlinePutonService.delByAssembleBid(bid);
			//修改组装单信息
			tccOfflineAssembleMapper.update(tccOfflineAssemble);

		}
		return R.ok("异常报错成功!");
	}


	/**
	 * 取消组装
	 * @param bid 组装单号
	 * @return
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R cancel(String bid) throws Exception{
		TccOfflineAssemble tccOfflineAssemble = new TccOfflineAssemble().setBid(bid).queryFirst();

		if (tccOfflineAssemble.getState() != TccOfflineAssembleEnum.State.NOT.value) {
			return R.error("数据已组装!");
		}

		List<TccOfflineAssembleItem> tccOfflineAssembleItemList = new TccOfflineAssembleItem().setPbid(bid).queryList();
		for (TccOfflineAssembleItem tccOfflineAssembleItem : tccOfflineAssembleItemList){
			TcgOfflinePurchaseInStorage tcgOfflinePurchaseInStorage = new TcgOfflinePurchaseInStorage().setId(tccOfflineAssembleItem.getOfflinePurchaseStorageId()).queryFirst();
			tcgOfflinePurchaseInStorage.setChw(null);
			//审核信息
			tcgOfflinePurchaseInStorage.setAuditingTime(null);
			tcgOfflinePurchaseInStorage.setAuditingUserId(null);
			tcgOfflinePurchaseInStorage.setStorageStatus(TcgOfflinePurchaseInStorageEnum.StorageStatus.STOCK_PENDING.value);
			tcgOfflinePurchaseInStorage.setPrintStatus(TcgOfflinePurchaseInStorageEnum.PrintStatus.NOT_PRINT.value);

			//解冻库存
			Integer sourceType = TccStockFrozenRunningEnum.SourceType.TCC_OFFLINEASSEMBLE_FINISH.value;
			tccStockControlService.thaw(tcgOfflinePurchaseInStorage.getStockControlId(), tcgOfflinePurchaseInStorage.getSubStorageNum(), sourceType, tccOfflineAssemble.getBid(), tccOfflineAssemble.getId());

			String remark = "线上商品组装取消组装 ,线上采购入库单号：" + tcgOfflinePurchaseInStorage.getBid();
			Integer numOut = tcgOfflinePurchaseInStorage.getSubStorageNum();
			Integer source = TccStockSourceEnum.Source.TCG_OfflineSPZZ.value;
			tccStockControlService.outWithRunning(tcgOfflinePurchaseInStorage.getStockControlId(), remark, numOut, bid,source,tccOfflineAssemble.getId());

			tcgOfflinePurchaseInStorage.setStockControlId(null);

			//查询采购计划子件数据
			TcgPurchaseByPlanSon tcgPurchasePlanSon = new TcgPurchaseByPlanSon()
					.addLeftJoin("TCG_PurchaseByOrderSon B ON B.PurchasePlanSonId = A.id")
					.where("B.id = " + tcgOfflinePurchaseInStorage.getPurchaseOrderSonId())
					.queryFirst();
			tcgPurchasePlanSon.setStoreAmount(tcgPurchasePlanSon.getStoreAmount().subtract(new BigDecimal(tcgOfflinePurchaseInStorage.getSubStorageNum())));
			tcgPurchasePlanSonMapper.update(tcgPurchasePlanSon);

			//判断是否完整
			TcgPurchasePlanGoods tcgPurchasePlanGoods = new TcgPurchasePlanGoods()
					.setId(tcgPurchasePlanSon.getPid())
					.queryFirst();
			if (tcgPurchasePlanGoods != null) {
				//取消采购计划母件完整性
				tcgPurchasePlanGoods.setStoreIntegrity(0);
				tcgPurchasePlanGoodsMapper.update(tcgPurchasePlanGoods);
			}

			tcgOfflinePurchaseInStorage.setAssembledStatus(TcgOfflinePurchaseInStorageEnum.AssembledStatus.NOT_ASSEMBLY.value);
			storageMapper.updatTcgOfflinePurchaseInStoragee(tcgOfflinePurchaseInStorage);

			tccOfflineAssembleItemMapper.deleteTrue(tccOfflineAssembleItem.getId());
		}
		tccOfflineAssembleMapper.deleteTrue(tccOfflineAssemble.getId());
		return R.ok("取消组装成功");
	}
}
